﻿using DynamicMouse.Native;
using Sage.WindowsMouse.Exceptions;
using Sage.WindowsMouse.Models;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace Sage.WindowsMouse
{
    /// <summary>
    /// 提供鼠标设置的管理服务
    /// </summary>
    public partial class MouseSettingsService
    {
        //private const uint STANDARD_FLAGS = Win32MouseApi.SPIF_UPDATEINIFILE | Win32MouseApi.SPIF_SENDCHANGE;
        private const uint STANDARD_FLAGS = Win32MouseApi.SPIF_UPDATEINIFILE | Win32MouseApi.SPIF_SENDCHANGE;

        /// <summary>
        /// 获取当前鼠标速度
        /// </summary>
        /// <returns>鼠标速度值(1-20)</returns>
        public static int GetMouseSpeed()
        {
            int speed = 0;
            if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_GETMOUSESPEED, 0, ref speed, 0))
            {
                throw new MouseSettingsException("获取鼠标速度失败");
            }
            return speed;
        }

        /// <summary>
        /// 设置鼠标速度
        /// </summary>
        /// <param name="speed">速度值(1-20)</param>
        public static void SetMouseSpeed(int speed)
        {
            if (speed is < 1 or > 20)
            {
                throw new ArgumentOutOfRangeException(nameof(speed), "鼠标速度必须在1-20之间");
            }

            try
            {
                // 对于 SPI_SETMOUSESPEED，第二个参数应该是 0，
                // 第三个参数是速度值的引用
                if (!Win32MouseApi.SystemParametersInfo(
                    Win32MouseApi.SPI_SETMOUSESPEED,
                    0,
                    speed, // 直接传递速度值
                    STANDARD_FLAGS))
                {
                    int error = Marshal.GetLastPInvokeError();
                    throw new MouseSettingsException($"设置鼠标速度失败，错误代码：{error}");
                }
            }
            catch (Exception ex)
            {
                throw new MouseSettingsException($"设置鼠标速度时发生错误：{ex.Message}");
            }
        }

        /// <summary>
        /// 获取双击时间
        /// </summary>
        public static int GetDoubleClickTime()
        {
            return (int)Win32MouseApi.GetDoubleClickTimeNative();
        }

        /// <summary>
        /// 设置双击时间
        /// </summary>
        /// <param name="milliseconds">双击时间(100-5000毫秒)</param>
        public static void SetDoubleClickTime(int milliseconds)
        {
            if (milliseconds is < 100 or > 5000)
            {
                throw new ArgumentOutOfRangeException(nameof(milliseconds), "双击时间必须在100-5000毫秒之间");
            }

            if (!Win32MouseApi.SetDoubleClickTimeNative((uint)milliseconds))
            {
                throw new MouseSettingsException("设置双击时间失败");
            }
        }

        /// <summary>
        /// 获取滚轮滚动行数
        /// </summary>
        public static int GetWheelScrollLines()
        {
            int lines = 0;
            if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_GETWHEELSCROLLLINES, 0, ref lines, 0))
            {
                throw new MouseSettingsException("获取滚轮滚动行数失败");
            }
            return lines;
        }

        /// <summary>
        /// 设置滚轮滚动行数
        /// </summary>
        public static void SetWheelScrollLines(int lines)
        {
            if (lines < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(lines), "滚轮滚动行数不能为负数");
            }

            if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_SETWHEELSCROLLLINES, 0, ref lines, STANDARD_FLAGS))
            {
                throw new MouseSettingsException("设置滚轮滚动行数失败");
            }
            //if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_SETWHEELSCROLLLINES, (uint)lines, IntPtr.Zero, STANDARD_FLAGS))
            //{
            //    throw new MouseSettingsException("设置滚轮滚动行数失败");
            //}
        }

        /// <summary>
        /// 获取当前所有鼠标设置
        /// </summary>
        public static MouseSettings GetCurrentSettings()
        {
            return new MouseSettings
            {
                Speed = GetMouseSpeed(),
                DoubleClickTime = GetDoubleClickTime(),
                WheelScrollLines = GetWheelScrollLines(),
                HoverTime = GetHoverTime(),
                HoverWidth = GetHoverWidth(),
                HoverHeight = GetHoverHeight(),
                MouseTrails = GetMouseTrails(),
                EnhancePointerPrecision = GetEnhancePointerPrecision()
            };
        }


        /// <summary>
        /// 获取鼠标悬停时间
        /// </summary>
        public static int GetHoverTime()
        {
            int time = 0;
            if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_GETMOUSEHOVERTIME, 0, ref time, 0))
            {
                throw new MouseSettingsException("获取鼠标悬停时间失败");
            }
            return time;
        }

        /// <summary>
        /// 设置鼠标悬停时间
        /// </summary>
        public static void SetHoverTime(int milliseconds)
        {
            if (milliseconds < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(milliseconds), "悬停时间不能为负数");
            }

            if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_SETMOUSEHOVERTIME, 0, ref milliseconds, STANDARD_FLAGS))
            {
                throw new MouseSettingsException("设置鼠标悬停时间失败");
            }

        }

        /// <summary>
        /// 获取鼠标悬停区域宽度
        /// </summary>
        public static int GetHoverWidth()
        {
            int width = 0;
            if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_GETMOUSEHOVERWIDTH, 0, ref width, 0))
            {
                throw new MouseSettingsException("获取鼠标悬停区域宽度失败");
            }
            return width;
        }

        /// <summary>
        /// 设置鼠标悬停区域宽度
        /// </summary>
        public static void SetHoverWidth(int width)
        {
            if (width < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(width), "悬停区域宽度不能为负数");
            }

            if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_SETMOUSEHOVERWIDTH, 0, ref width, STANDARD_FLAGS))
            {
                throw new MouseSettingsException("设置鼠标悬停区域宽度失败");
            }

        }

        /// <summary>
        /// 获取鼠标悬停区域高度
        /// </summary>
        public static int GetHoverHeight()
        {
            int height = 0;
            if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_GETMOUSEHOVERHEIGHT, 0, ref height, 0))
            {
                throw new MouseSettingsException("获取鼠标悬停区域高度失败");
            }
            return height;
        }

        /// <summary>
        /// 设置鼠标悬停区域高度
        /// </summary>
        public static void SetHoverHeight(int height)
        {
            if (height < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(height), "悬停区域高度不能为负数");
            }

            if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_SETMOUSEHOVERHEIGHT, 0, ref height, STANDARD_FLAGS))
            {
                throw new MouseSettingsException("设置鼠标悬停区域高度失败");
            }

        }

        /// <summary>
        /// 获取鼠标轨迹设置
        /// </summary>
        public static int GetMouseTrails()
        {
            int trails = 0;
            if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_GETMOUSETRAILS, 0, ref trails, 0))
            {
                throw new MouseSettingsException("获取鼠标轨迹设置失败");
            }
            return trails;
        }

        /// <summary>
        /// 设置鼠标轨迹
        /// </summary>
        /// <param name="value">轨迹值(0-9)</param>
        public static void SetMouseTrails(int value)
        {
            if (value is < 0 or > 9)
            {
                throw new ArgumentOutOfRangeException(nameof(value), "鼠标轨迹值必须在0-9之间");
            }

            if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_SETMOUSETRAILS, 0, ref value, STANDARD_FLAGS))
            {
                throw new MouseSettingsException("设置鼠标轨迹失败");
            }
        }

        /// <summary>
        /// 获取增强指针精度设置
        /// </summary>
        public static bool GetEnhancePointerPrecision()
        {
            int[] mouseParams = new int[3];
            if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_GETMOUSE, 0, ref mouseParams[0], 0))
            {
                throw new MouseSettingsException("获取增强指针精度设置失败");
            }
            return mouseParams[2] != 0;
        }

        /// <summary>
        /// 设置增强指针精度
        /// </summary>
        public static void SetEnhancePointerPrecision(bool enable)
        {
            int[] mouseParams = new int[3];
            if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_GETMOUSE, 0, ref mouseParams[0], 0))
            {
                throw new MouseSettingsException("获取当前鼠标参数失败");
            }

            mouseParams[2] = enable ? 1 : 0;

            if (!Win32MouseApi.SystemParametersInfo(Win32MouseApi.SPI_SETMOUSE, 0, ref mouseParams[0], STANDARD_FLAGS))
            {
                throw new MouseSettingsException("设置增强指针精度失败");
            }
        }

        /// <summary>
        /// 应用鼠标设置
        /// </summary>
        private static void ApplySettings(MouseSettings settings)
        {
            if (settings.Speed is >= 1 and <= 20)
            {
                SetMouseSpeed(settings.Speed);
            }
            else if (settings.Speed != -1)
            {
                Debug.WriteLine($"跳过无效的鼠标速度设置: {settings.Speed}");
            }

            if (settings.DoubleClickTime is >= 100 and <= 5000)
            {
                SetDoubleClickTime(settings.DoubleClickTime);
            }
            else if (settings.DoubleClickTime != -1)
            {
                Debug.WriteLine($"跳过无效的双击时间设置: {settings.DoubleClickTime}");
            }

            if (settings.WheelScrollLines >= 0)
            {
                SetWheelScrollLines(settings.WheelScrollLines);
            }
            else if (settings.WheelScrollLines != -1)
            {
                Debug.WriteLine($"跳过无效的滚轮滚动行数设置: {settings.WheelScrollLines}");
            }

            if (settings.HoverTime >= 0)
            {
                SetHoverTime(settings.HoverTime);
            }
            else if (settings.HoverTime != -1)
            {
                Debug.WriteLine($"跳过无效的悬停时间设置: {settings.HoverTime}");
            }

            if (settings.HoverWidth >= 0)
            {
                SetHoverWidth(settings.HoverWidth);
            }
            else if (settings.HoverWidth != -1)
            {
                Debug.WriteLine($"跳过无效的悬停宽度设置: {settings.HoverWidth}");
            }

            if (settings.HoverHeight >= 0)
            {
                SetHoverHeight(settings.HoverHeight);
            }
            else if (settings.HoverHeight != -1)
            {
                Debug.WriteLine($"跳过无效的悬停高度设置: {settings.HoverHeight}");
            }

            if (settings.MouseTrails is >= 0 and <= 9)
            {
                SetMouseTrails(settings.MouseTrails);
            }
            else if (settings.MouseTrails != -1)
            {
                Debug.WriteLine($"跳过无效的鼠标轨迹设置: {settings.MouseTrails}");
            }

            if (settings.EnhancePointerPrecision.HasValue)
            {
                SetEnhancePointerPrecision(settings.EnhancePointerPrecision.Value);
            }
            else
            {
                Debug.WriteLine($"跳过无效的鼠标增强精度设置");
            }
        }
    }
}
